package com.hc.cursorutils.lambda;


import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.io.*;

public class SerializedLambda implements Serializable {
    private static final long serialVersionUID = 8025925345765570181L;
    private Class<?> capturingClass;
    private String functionalInterfaceClass;
    private String functionalInterfaceMethodName;
    private String functionalInterfaceMethodSignature;
    private String implClass;
    private String implMethodName;
    private String implMethodSignature;
    private int implMethodKind;
    private String instantiatedMethodType;
    private Object[] capturedArgs;
    public SerializedLambda() {
    }

    /**
     * 反序列化lambda表达式为SerializedLambda
     * @param lambda
     * @return
     */
    public static SerializedLambda resolve(SFunction<?, ?> lambda) {
        if (!lambda.getClass().isSynthetic()) {
            throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类", new Object[0]);
        } else {
            try {
                ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(serialize(lambda))) {
                    protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
                        Class clazz;
                        try {
                            clazz = com.baomidou.mybatisplus.core.toolkit.ClassUtils.toClassConfident(objectStreamClass.getName());
                        } catch (Exception var4) {
                            clazz = super.resolveClass(objectStreamClass);
                        }

                        return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
                    }
                };
                Throwable var2 = null;

                SerializedLambda var3;
                try {
                    var3 = (SerializedLambda)objIn.readObject();
                } catch (Throwable var13) {
                    var2 = var13;
                    throw var13;
                } finally {
                    if (objIn != null) {
                        if (var2 != null) {
                            try {
                                objIn.close();
                            } catch (Throwable var12) {
                                var2.addSuppressed(var12);
                            }
                        } else {
                            objIn.close();
                        }
                    }

                }

                return var3;
            } catch (IOException | ClassNotFoundException var15) {
                throw ExceptionUtils.mpe("This is impossible to happen", var15, new Object[0]);
            }
        }
    }

    public String getFunctionalInterfaceClassName() {
        return this.normalizedName(this.functionalInterfaceClass);
    }

    public Class<?> getImplClass() {
        return com.baomidou.mybatisplus.core.toolkit.ClassUtils.toClassConfident(this.getImplClassName());
    }

    public String getImplClassName() {
        return this.normalizedName(this.implClass);
    }

    public String getImplMethodName() {
        return this.implMethodName;
    }

    private String normalizedName(String name) {
        return name.replace('/', '.');
    }

    public Class<?> getInstantiatedType() {
        String instantiatedTypeName = this.normalizedName(this.instantiatedMethodType.substring(2, this.instantiatedMethodType.indexOf(59)));
        return ClassUtils.toClassConfident(instantiatedTypeName);
    }

    public String toString() {
        String interfaceName = this.getFunctionalInterfaceClassName();
        String implName = this.getImplClassName();
        return String.format("%s -> %s::%s", interfaceName.substring(interfaceName.lastIndexOf(46) + 1), implName.substring(implName.lastIndexOf(46) + 1), this.implMethodName);
    }

    public static byte[] serialize(Object object) {
        if (object == null) {
            return null;
        } else {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);

            try {
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                Throwable var3 = null;

                try {
                    oos.writeObject(object);
                    oos.flush();
                } catch (Throwable var13) {
                    var3 = var13;
                    throw var13;
                } finally {
                    if (oos != null) {
                        if (var3 != null) {
                            try {
                                oos.close();
                            } catch (Throwable var12) {
                                var3.addSuppressed(var12);
                            }
                        } else {
                            oos.close();
                        }
                    }

                }
            } catch (IOException var15) {
                throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), var15);
            }

            return baos.toByteArray();
        }
    }
}
